package com.jfinal.core;

import java.util.List;
import java.util.TimerTask;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;






import net.onewfour.dao.detail.DBAction;
import net.onewfour.dao.detail.DbTimer;

import com.jfinal.core.Action;
import com.jfinal.core.ActionException;
import com.jfinal.core.ActionInvocation;
import com.jfinal.core.ActionRender;
import com.jfinal.core.ActionReporter;
import com.jfinal.core.Controller;
import com.jfinal.handler.Handler;
import com.jfinal.log.Logger;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.render.Render;
import com.jfinal.render.RenderException;
import com.jfinal.render.RenderFactory;

/***
 * handlers
 * @author Marc
 * @version 1.0
 */
public class CMSHandlers extends Handler {
	
	public static boolean devMode;
	private static final RenderFactory renderFactory = RenderFactory.me();
	private static final Logger log = Logger.getLogger(CMSHandlers.class);
	private static CMSActionMapping actionMapping = new CMSActionMapping() ;  
	
	/**
	 * 加载中心
	 * @user Marc
	 * @createtime 2015年1月27日 下午5:57:29
	 */
	public static void load(){
		devMode = Config.getConstants().getDevMode();
		log.info("start CMS Control");
		loadControl();
		loadTimer();
		log.info("start OK ......");
	}

	/**
	 * 加载定时器
	 * @user Marc
	 * @createtime 2015年1月27日 下午5:57:44
	 */
	private static void loadTimer() {
		List<Record>  list = DbTimer.instance().getAllTimer();
		for (int i = 0; i < list.size(); i++) {
			Record cord = list.get(i);
			String className = cord.get("className");
			long timerInt = cord.get("timer");
			try {
				TimerTask task = (TimerTask) Class.forName(className).newInstance();
				java.util.Timer timer = new java.util.Timer(true); 
				timer.schedule(task, 1000*60, timerInt == 0?1000*60*60:timerInt);
			}catch (Exception e) {
				log.debug("Timer:"+className+"初始化失败");
			}
		}
	}

	/***
	 * 加载控制类
	 * @user Marc
	 * @createtime 2015年1月27日 下午5:57:22
	 */
	private static void loadControl() {
		List<Record> list = DBAction.Instance().getAllAction();
		
		for (int i = 0; i < list.size(); i++) {
			String url = list.get(i).getStr("url");
			String action = list.get(i).getStr("action");
			String type = list.get(i).getStr("type");
			String note = list.get(i).getStr("note");
			int isadmin = list.get(i).getInt("isadmin");
			actionMapping.addAction(url,action,type,note,isadmin);
		}
	}
	
	public static String getAdminUrl(){
		return actionMapping.getAdminURL();
	}
	
	/**
	 * handle
	 * 1: Action action = actionMapping.getAction(target)
	 * 2: new ActionInvocation(...).invoke()
	 * 3: render(...)
	 */
	public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
		if (target.indexOf(".") != -1) {
			return ;
		}
		
		isHandled[0] = true;
		String[] urlPara = {null};
		Action action = actionMapping.getAction(target, urlPara);
		
		if (action == null) {
			if (log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
			}
			renderFactory.getErrorRender(404).setContext(request, response).render();
			return ;
		}
		
		try {
			Controller controller = action.getControllerClass().newInstance();
			controller.init(request, response, urlPara[0]);
			log.info("URL:"+target);
			if (devMode) {
				boolean isMultipartRequest = ActionReporter.reportCommonRequest(controller, action);
				new ActionInvocation(action, controller).invoke();
				if (isMultipartRequest) ActionReporter.reportMultipartRequest(controller, action);
			}
			else {
				new ActionInvocation(action, controller).invoke();
			}
			
			Render render = controller.getRender();
			if (render instanceof ActionRender) {
				String actionUrl = ((ActionRender)render).getActionUrl();
				if (target.equals(actionUrl))
					throw new RuntimeException("The forward action url is the same as before.");
				else
					handle(actionUrl, request, response, isHandled);
				return ;
			}
			
			if (render == null)
				render = renderFactory.getDefaultRender(action.getViewPath() + action.getMethodName());
			render.setContext(request, response, action.getViewPath()).render();
		}
		catch (RenderException e) {
			if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, e);
			}
		}
		catch (ActionException e) {
			int errorCode = e.getErrorCode();
			if (errorCode == 404 && log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("404 Not Found: " + (qs == null ? target : target + "?" + qs));
			}
			else if (errorCode == 401 && log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("401 Unauthorized: " + (qs == null ? target : target + "?" + qs));
			}
			else if (errorCode == 403 && log.isWarnEnabled()) {
				String qs = request.getQueryString();
				log.warn("403 Forbidden: " + (qs == null ? target : target + "?" + qs));
			}
			else if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, e);
			}
			e.getErrorRender().setContext(request, response).render();
		}
		catch (Exception e) {
			if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, e);
			}
			renderFactory.getErrorRender(500).setContext(request, response).render();
		}
	}
}
